package com.demo.java.concurrent;

import com.demo.java.utils.ThreadUtils;

import java.util.concurrent.TimeUnit;

/**
 * 锁的内存语义:
 * 当线程释放锁时，JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。
 * 当线程获取锁时，JMM会把该线程对应的本地内存置为无效。从而使得被监视器保护的临界区代码必须要从主内存中去读取共享变量。
 * 对比锁释放-获取的内存语义与volatile写-读的内存语义，可以看出：锁释放与volatile写有相同的内存语义；锁获取与volatile读有相同的内存语义。
 *
 * 线程A释放一个锁，实质上是线程A向接下来将要获取这个锁的某个线程发出了（线程A对共享变量所做修改的）消息。
 * 线程B获取一个锁，实质上是线程B接收了之前某个线程发出的（在释放这个锁之前对共享变量所做修改的）消息。
 * 线程A释放锁，随后线程B获取这个锁，这个过程实质上是线程A通过主内存向线程B发送消息。
 */
public class VolatileTest {
    private static final Object obj = new Object();
    static int a = 0;

    public static void main(String[] args) {
        Thread t = new Thread(() -> {
//            System.out.println("child a: " + a);
            synchronized (obj) {}// 与System.out.println的作用相等
            ThreadUtils.sleep(1, TimeUnit.SECONDS);
            a ++;
            synchronized (obj) {}
//            System.out.println("child end a: " + a);
        });
        t.start();
        while (a == 0) {
            synchronized (obj) {}
//            System.out.println("加了这一句就不会出现死循环");
        }
//        System.out.println("main end" + a);
    }
}
